package com.ship.dispatch.bpm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import cn.hutool.json.JSONObject;
import com.ship.common.core.base.Page;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;

import com.ship.dispatch.bean.ConShipping;
import com.ship.dispatch.bean.SpDispatchSchemeExecute;
import com.ship.dispatch.bean.SpFobSublease;
import com.ship.dispatch.bean.SpPortInformation;
import com.ship.dispatch.bean.fob.SpBpmCoordinate;

import com.ship.dispatch.bean.fob.SpFobBaseBean;
import com.ship.dispatch.bean.orderPay.SpPaymentOrder;
import com.ship.dispatch.bpm.enums.BpmComment;
import com.ship.dispatch.bpm.factory.BpmServiceFactory;
import com.ship.dispatch.bpm.service.BpmProcessDefinitionService;
import com.ship.dispatch.bpm.service.ProcessInstanceService;
import com.ship.dispatch.bpm.service.TaskService;
import com.ship.dispatch.bpm.service.dto.DeliveryNoticeDayDto;
import com.ship.dispatch.bpm.utils.BpmTaskUtil;
import com.ship.dispatch.bpm.utils.FlowableUtils;
import com.ship.dispatch.bpm.utils.JsonUtils;
import com.ship.dispatch.bpm.vo.BpmQueryVo;
import com.ship.dispatch.bpm.vo.BpmTaskVo;
import com.ship.dispatch.bpm.vo.dto.*;
import com.ship.dispatch.bpm.vo.task.BpmTaskApproveReqVO;
import com.ship.dispatch.bpm.vo.task.BpmTaskTodoItemRespVO;
import com.ship.dispatch.mapper.SpPortInformationMapper;
import com.ship.dispatch.service.*;
import com.ship.dispatch.service.bpm.BpmInstanceServiceApi;
import com.ship.dispatch.service.fob.FobBaseService;
import com.ship.dispatch.service.fob.FobService;
import com.ship.dispatch.service.fob.SpBpmCoordinateService;
import com.ship.dispatch.service.fob.SpFobTemplateService;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.dispatch.service.orderPay.SpPaymentOrderService;
import com.ship.dispatch.service.shipBusiness.SmShipReportService;
import com.ship.dispatch.vo.fileTemplate.NodeVO;
import com.ship.system.api.ConBpmResultService;
import com.ship.system.api.RemoteUserService;
import com.ship.system.api.domain.SysUser;
import io.swagger.models.auth.In;
import liquibase.pro.packaged.L;
import liquibase.pro.packaged.S;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceQuery;
import org.flowable.engine.task.Comment;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.history.HistoricIdentityLink;
import org.flowable.task.api.DelegationState;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.api.history.HistoricTaskInstanceQuery;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntity;
import org.flowable.variable.service.impl.persistence.entity.HistoricVariableInstanceEntityImpl;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 *@title TaskServiceImpl
 *@description
 *@author yl
 *@create 2023/12/13 0013
 */

@Service
public class TaskServiceImpl extends BpmServiceFactory implements TaskService {


    private final Map formTemplate;


    private static Map<String,List<TaskDto>> taskMap = new HashMap<>();

    @Autowired
    SpBpmCoordinateService spBpmCoordinateService;

    @Autowired
    SpFobTemplateService spFobTemplateService;

    @Autowired(required = false)
    SpPortInformationMapper spPortInformationMapper;
    @Autowired
    SpDispatchSchemeExecuteService spDispatchSchemeExecuteService;
    @Autowired
    SpFobSubleaseService spFobSubleaseService;
    @Resource
    private RuntimeService runtimeService;

    @Autowired
    private ProcessInstanceService processInstanceService;

    @Autowired
    BpmProcessDefinitionService processDefinitionService;

    @Resource
    @Lazy
    TzFuelReportService tzFuelReportService;

    @Autowired
    public TaskServiceImpl() {
        this.formTemplate = readJsonFile();
    }

    /**
     * 获取所有流程中所有节点
     * @return
     */
    @Override
    public List<FormTemplate> getFormTemplates(){
        List<FormTemplate> formTemplates = new ArrayList<>();

        if(formTemplate!=null){
            Collection<Object> objects = formTemplate.values();
            for (Object item1 : objects){
                JSONArray jsonNode = (JSONArray) item1;
                for (Object item : jsonNode){
                    JSONObject object = (JSONObject) item;
                    FormTemplate template = new FormTemplate();
                    template.setId(object.get("id").toString());
                    template.setName(object.get("name").toString());
//                    JSONArray childs = (JSONArray) object.get("template");
//                    List<Field> fields = new ArrayList<>();
//                    for(Object child:childs){
//                        Field tempField = new Field();
//                        JSONObject childItem = (JSONObject) child;
//                        tempField.setFieldCode(childItem.get("fieldCode").toString());
//                        tempField.setFieldName(childItem.get("fieldName").toString());
//                        tempField.setType(childItem.get("type").toString());
//                        tempField.setDataType(childItem.get("dataType")!=null?childItem.get("dataType").toString():"");
//                        if("emailTemplate".equals(childItem.get("dataType"))){ // 邮件模板
//                            List<FieldOptions> options = spFobTemplateService.getTemplateInfoByServiceKey(template.getId(),"email");
//                            tempField.setOptions(options);
//                        } else if("fileTemplate".equals(childItem.get("dataType"))){ // 邮件模板
//                            List<FieldOptions> options = spFobTemplateService.getTemplateInfoByServiceKey(template.getId(),"file");
//                            tempField.setOptions(options);
//                        }
//                        fields.add(tempField);
//                    }
//                    template.setTemplate(fields);
                    formTemplates.add(template);
                }
            }
        }
        return formTemplates;
    }

    /**
     * 提交任务任务
     * @param taskVo
     * @return
     */
    @Override
    public JsonResult complete(BpmTaskVo taskVo) {
        Task task = taskService.createTaskQuery().taskId(taskVo.getTaskId()).singleResult();
        //pending标识尚未开始或者正在执行
        if(task==null)
            return JsonResult.success();
            //throw new BusException("", BaseResultCode.GENERAL_ERROR);
        if (DelegationState.PENDING.equals(task.getDelegationState())) {
            taskService.addComment(taskVo.getTaskId(), task.getProcessInstanceId(), BpmComment.DELEGATE.getType(), taskVo.getComment());
            taskService.resolveTask(taskVo.getTaskId(), taskVo.getVariables());
        } else {
            taskService.addComment(taskVo.getTaskId(), task.getProcessInstanceId(), BpmComment.NORMAL.getType(), taskVo.getComment());
            //TODO:后期从登录账号中获取登录人信息
            taskService.setAssignee(taskVo.getTaskId(), SecurityUtils.getStringUserId());
            taskService.complete(taskVo.getTaskId(), taskVo.getVariables());
        }
        return JsonResult.success(task.getName());
    }



    /**
     * 审批驳回
     * @param flowTaskVo
     */
    @Override
    public void taskReject(BpmTaskVo flowTaskVo) {
        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new RuntimeException("任务处于挂起状态!");
        }
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        // 获取全部节点列表，包含子节点
        Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
        // 获取当前任务节点元素
        FlowElement source = null;
        if (allElements != null) {
            for (FlowElement flowElement : allElements) {
                // 类型为用户节点
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    // 获取节点信息
                    source = flowElement;
                }
            }
        }

        // 目的获取所有跳转到的节点 targetIds
        // 获取当前节点的所有父级用户任务节点
        // 深度优先算法思想：延边迭代深入
        List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null);
        if (parentUserTaskList == null || parentUserTaskList.size() == 0) {
            throw new RuntimeException("当前节点为初始任务节点，不能驳回");
        }
        // 获取活动 ID 即节点 Key
        List<String> parentUserTaskKeyList = new ArrayList<>();
        parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId()));
        // 获取全部历史节点活动实例，即已经走过的节点历史，数据采用开始时间升序
        List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list();
        // 数据清洗，将回滚导致的脏数据清洗掉
        List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList);
        // 此时历史任务实例为倒序，获取最后走的节点
        List<String> targetIds = new ArrayList<>();
        // 循环结束标识，遇到当前目标节点的次数
        int number = 0;
        StringBuilder parentHistoricTaskKey = new StringBuilder();
        for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) {
            // 当会签时候会出现特殊的，连续都是同一个节点历史数据的情况，这种时候跳过
            if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) {
                continue;
            }
            parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey);
            if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) {
                number++;
            }
            // 在数据清洗后，历史节点就是唯一一条从起始到当前节点的历史记录，理论上每个点只会出现一次
            // 在流程中如果出现循环，那么每次循环中间的点也只会出现一次，再出现就是下次循环
            // number == 1，第一次遇到当前节点
            // number == 2，第二次遇到，代表最后一次的循环范围
            if (number == 2) {
                break;
            }
            // 如果当前历史节点，属于父级的节点，说明最后一次经过了这个点，需要退回这个点
            if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) {
                targetIds.add(historicTaskInstanceKey);
            }
        }


        // 目的获取所有需要被跳转的节点 currentIds
        // 取其中一个父级任务，因为后续要么存在公共网关，要么就是串行公共线路
        UserTask oneUserTask = parentUserTaskList.get(0);
        // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
        List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<String> runTaskKeyList = new ArrayList<>();
        runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
        // 需驳回任务列表
        List<String> currentIds = new ArrayList<>();
        // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
        List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null);
        currentUserTaskList.forEach(item -> currentIds.add(item.getId()));


        // 规定：并行网关之前节点必须需存在唯一用户任务节点，如果出现多个任务节点，则并行网关节点默认为结束节点，原因为不考虑多对多情况
        if (targetIds.size() > 1 && currentIds.size() > 1) {
            throw new RuntimeException("任务出现多对多情况，无法撤回");
        }

        // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
        List<String> currentTaskIds = new ArrayList<>();
        currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
            if (currentId.equals(runTask.getTaskDefinitionKey())) {
                currentTaskIds.add(runTask.getId());
            }
        }));
        // 设置驳回意见
        currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), BpmComment.REJECT.getType(), flowTaskVo.getComment()));

        try {
            // 如果父级任务多于 1 个，说明当前节点不是并行节点，原因为不考虑多对多情况
            if (targetIds.size() > 1) {
                // 1 对 多任务跳转，currentIds 当前节点(1)，targetIds 跳转到的节点(多)
                runtimeService.createChangeActivityStateBuilder()
                        .processInstanceId(task.getProcessInstanceId()).
                        moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState();
            }
            // 如果父级任务只有一个，因此当前任务可能为网关中的任务
            if (targetIds.size() == 1) {
                // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetIds.get(0) 跳转到的节点(1)
                runtimeService.createChangeActivityStateBuilder()
                        .processInstanceId(task.getProcessInstanceId())
                        .moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState();
            }
        } catch (FlowableObjectNotFoundException e) {
            throw new RuntimeException("未找到流程实例，流程可能已发生变化");
        } catch (FlowableException e) {
            throw new RuntimeException("无法取消或开始活动");
        }

    }

    @Override
    public void taskReturn(BpmTaskVo flowTaskVo) {
        if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) {
            throw new RuntimeException("任务处于挂起状态");
        }
        // 当前任务 task
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        // 获取全部节点列表，包含子节点
        Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null);
        // 获取当前任务节点元素
        FlowElement source = null;
        // 获取跳转的节点元素
        FlowElement target = null;
        if (allElements != null) {
            for (FlowElement flowElement : allElements) {
                // 当前任务节点元素
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = flowElement;
                }
                // 跳转的节点元素
                if (flowElement.getId().equals(flowTaskVo.getTargetKey())) {
                    target = flowElement;
                }
            }
        }

        // 从当前节点向前扫描
        // 如果存在路线上不存在目标节点，说明目标节点是在网关上或非同一路线上，不可跳转
        // 否则目标节点相对于当前节点，属于串行
        Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null);
        if (!isSequential) {
            throw new RuntimeException("当前节点相对于目标节点，不属于串行关系，无法回退");
        }


        // 获取所有正常进行的任务节点 Key，这些任务不能直接使用，需要找出其中需要撤回的任务
        List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list();
        List<String> runTaskKeyList = new ArrayList<>();
        runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey()));
        // 需退回任务列表
        List<String> currentIds = new ArrayList<>();
        // 通过父级网关的出口连线，结合 runTaskList 比对，获取需要撤回的任务
        List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null);
        currentUserTaskList.forEach(item -> currentIds.add(item.getId()));

        // 循环获取那些需要被撤回的节点的ID，用来设置驳回原因
        List<String> currentTaskIds = new ArrayList<>();
        currentIds.forEach(currentId -> runTaskList.forEach(runTask -> {
            if (currentId.equals(runTask.getTaskDefinitionKey())) {
                currentTaskIds.add(runTask.getId());
            }
        }));
        // 设置回退意见
        currentTaskIds.forEach(currentTaskId -> taskService.addComment(currentTaskId, task.getProcessInstanceId(), BpmComment.REBACK.getType(), flowTaskVo.getComment()));

        try {
            // 1 对 1 或 多 对 1 情况，currentIds 当前要跳转的节点列表(1或多)，targetKey 跳转到的节点(1)
            runtimeService.createChangeActivityStateBuilder()
                    .processInstanceId(task.getProcessInstanceId())
                    .moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState();
        } catch (FlowableObjectNotFoundException e) {
            throw new RuntimeException("未找到流程实例，流程可能已发生变化");
        } catch (FlowableException e) {
            throw new RuntimeException("无法取消或开始活动");
        }
    }

    /**
     * 获取可回退节点
     * @param flowTaskVo
     * @return
     */
    @Override
    public JsonResult findReturnTaskList(BpmTaskVo flowTaskVo) {
        Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult();
        // 获取流程定义信息
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
        // 获取所有节点信息，暂不考虑子流程情况
        Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0);
        Collection<FlowElement> flowElements = process.getFlowElements();
        // 获取当前任务节点元素
        UserTask source = null;
        if (flowElements != null) {
            for (FlowElement flowElement : flowElements) {
                // 类型为用户节点
                if (flowElement.getId().equals(task.getTaskDefinitionKey())) {
                    source = (UserTask) flowElement;
                }
            }
        }
        // 获取节点的所有路线
        List<List<UserTask>> roads = FlowableUtils.findRoad(source, null, null, null);
        // 可回退的节点列表
        List<UserTask> userTaskList = new ArrayList<>();
        for (List<UserTask> road : roads) {
            if (userTaskList.size() == 0) {
                // 还没有可回退节点直接添加
                userTaskList = road;
            } else {
                // 如果已有回退节点，则比对取交集部分
                userTaskList.retainAll(road);
            }
        }
        return JsonResult.success(userTaskList);
    }

    @Override
    public void deleteTask(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void claim(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void unClaim(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void delegateTask(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void resolveTask(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void assignTask(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void addMultiInstanceExecution(BpmTaskVo flowTaskVo) {

    }

    @Override
    public void deleteMultiInstanceExecution(BpmTaskVo flowTaskVo) {

    }

    @Override
    public JsonResult myProcess(BpmQueryVo queryVo) {
        return null;
    }

    @Override
    public JsonResult stopProcess(BpmTaskVo flowTaskVo) {
        return null;
    }

    @Override
    public JsonResult revokeProcess(BpmTaskVo flowTaskVo) {
        return null;
    }

    @Override
    public JsonResult todoList(BpmQueryVo queryVo) {
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(SecurityUtils.getUsername()).list();
        return JsonResult.success(tasks);
    }

    @Override
    public JsonResult finishedList(BpmQueryVo queryVo) {
        return null;
    }

    @Override
    public JsonResult flowRecord(String procInsId) {
        return JsonResult.success(findActivitiOrFinishTask(procInsId));
    }

    @Override
    public InputStream diagram(String processId) {
        return null;
    }

    @Override
    public JsonResult getFlowViewer(String procInsId, String executionId) {
        return null;
    }

    @Override
    public JsonResult processVariables(String taskId) {
        return null;
    }

    @Override
    public JsonResult flowFormData(String deployId) {
        return null;
    }

    @Override
    public JsonResult flowXmlAndNode(String procInsId, String deployId) {
        return null;
    }

    @Override
    public JsonResult flowTaskForm(String taskId) throws Exception {
        return null;
    }

    @Override
    public JsonResult todoProcessInstanceList(String processInstaneId) {
        //TODO:后期从登录账号中获取登录人信息
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstaneId)
                .active().taskCandidateOrAssigned("1").orderByTaskCreateTime().desc().list();
        List<BpmTaskDto> hisFlowList = new ArrayList<>();
        for (Task histIns : tasks) {
            if (StringUtils.isNotBlank(histIns.getId())) {
                BpmTaskDto flowTask = new BpmTaskDto();
                flowTask.setTaskId(histIns.getId());
                flowTask.setTaskName(histIns.getName());
                flowTask.setCategory(histIns.getCategory());
                flowTask.setCreateTime(histIns.getCreateTime());
                hisFlowList.add(flowTask);
            }
        }
        return JsonResult.success(hisFlowList);
    }

    @Resource
    @Lazy
    RemoteUserService remoteUserService;
    public List<BpmTaskDto> findActivitiOrFinishTask(String procInsId) {
        // 获得任务列表
        List<BpmTaskDto> hisFlowList = new ArrayList<>();
        if (StringUtils.isNotBlank(procInsId)) {
            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(procInsId)
                    .orderByHistoricTaskInstanceStartTime().desc() // 创建时间倒序
                    .list();
            for (HistoricTaskInstance histIns : tasks) {
                if (StringUtils.isNotBlank(histIns.getId())) {
                    BpmTaskDto flowTask = new BpmTaskDto();
                    flowTask.setTaskId(histIns.getId());
                    HistoricVariableInstance resolveTaskStatus = historyService.createHistoricVariableInstanceQuery().taskId(histIns.getId()).variableName("resolveTaskStatus").singleResult();
                   // Object resolveTaskStatus = historyService.getva
                           // taskService.getVariableLocal(histIns.getId(),"resolveTaskStatus");
                    //Map<String,Object> map = histIns.gettas();
                    if(resolveTaskStatus!=null && resolveTaskStatus.getValue()!=null){
                        flowTask.setStatus(Integer.parseInt(resolveTaskStatus.getValue()+""));
                    }
                    flowTask.setTaskName(histIns.getName());
                    flowTask.setCategory(histIns.getCategory());
                    flowTask.setCreateTime(histIns.getStartTime());
                    flowTask.setFinishTime(histIns.getEndTime());
                    flowTask.setCategory(histIns.getCategory());
                    flowTask.setDueDate(histIns.getDueDate());
                    flowTask.setTaskDefKey(histIns.getTaskDefinitionKey());
                    if (StringUtils.isNotBlank(histIns.getAssignee())) {
                        // 获取用户信息封装
                        flowTask.setAssigneeId(histIns.getAssignee());
                        //TODO 获取用户信息封装处理人
                        SysUser user = remoteUserService.getUserByName(histIns.getAssignee());
                        if(user!=null){
                            flowTask.setAssigneeName(user.getNickName());
                        }else {
                            flowTask.setAssigneeName(histIns.getAssignee());
                        }
                        //
                    }
                    // 展示审批人员
                    List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getId());
                    StringBuilder stringBuilder = new StringBuilder();
                    for (HistoricIdentityLink identityLink : linksForTask) {
                        // 候选人
                        if ("candidate".equals(identityLink.getType())) {
                            if (StringUtils.isNotBlank(identityLink.getUserId())) {
                                // 绑定人员信息
                               SysUser user=  remoteUserService.getUserByName(identityLink.getUserId());
                               if(user!=null){
                                   stringBuilder.append(user.getNickName()).append(",");
                               }
                            }
                        }
                    }
                    if (StringUtils.isNotBlank(stringBuilder)) {
                        flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1));
                    }
                    flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis()));
                    // 获取意见评论内容
                    List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId());
                    commentList.forEach(comment -> {
                        if (histIns.getId().equals(comment.getTaskId())) {
                            flowTask.setComment(BpmCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build());
                        }
                    });
                    hisFlowList.add(flowTask);
                }
            }
        }
        return hisFlowList;
    }

    public List<BpmTaskDto> findActivitiOrFinishTaskResult(String procInsId) {
        // 获得任务列表
        List<BpmTaskDto> hisFlowList = new ArrayList<>();
        if (StringUtils.isNotBlank(procInsId)) {
            List<HistoricTaskInstance> tasks = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(procInsId)
                    .orderByHistoricTaskInstanceStartTime().asc() // 创建时间sheng序
                    .list();
            for (HistoricTaskInstance histIns : tasks) {
                if (StringUtils.isNotBlank(histIns.getId())) {
                    BpmTaskDto flowTask = new BpmTaskDto();
                    flowTask.setTaskId(histIns.getId());
                    flowTask.setTaskName(histIns.getName());
                    flowTask.setCategory(histIns.getCategory());
                    flowTask.setCreateTime(histIns.getStartTime());
                    flowTask.setFinishTime(histIns.getEndTime());
                    flowTask.setCategory(histIns.getCategory());
                    flowTask.setDueDate(histIns.getDueDate());
                    flowTask.setAssigneeId(histIns.getAssignee());
                    hisFlowList.add(flowTask);
                }
            }
        }
        hisFlowList.sort(Comparator.comparing(BpmTaskDto::getCreateTime));
        return hisFlowList;
    }

    //获取流程任务信息
    @Override
    public JsonResult getProcessAllTaskINfo(String processInstaneId) {
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstaneId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
        if(processDefinition == null){
            return JsonResult.failed("流程定义不存在，请联系管理员确认后重新发起");
        }
        List<TaskDto> tasks = null;
        if(taskMap.containsKey(instance.getProcessDefinitionId())){
            tasks = taskMap.get(instance.getProcessDefinitionId());
        }else {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
            tasks = readBpmNodeInfo(processDefinition.getKey(),instance.getProcessDefinitionId(),bpmnModel);
        }
        List<BpmTaskDto> list = findActivitiOrFinishTask(processInstaneId);
        Map<String,BpmTaskDto> maps = list.stream().collect(Collectors.toMap(BpmTaskDto::getTaskDefKey,item->item));
        for(TaskDto dto : tasks){
            dto.setStatus(-1);
            //taskService.getc
            dto.setParentNode(null);
            if(maps.containsKey(dto.getId())){
                BpmTaskDto temp = maps.get(dto.getId());
                dto.setTaskId(temp.getTaskId());
                dto.setComment(temp.getComment());
                dto.setCreateTime(temp.getCreateTime());
                dto.setFinishTime(temp.getFinishTime());
                dto.setDuration(temp.getDuration());
                if(temp.getAssigneeId()!=null){
                    dto.setAssigneeId(temp.getAssigneeId());
                    dto.setAssigneeName(temp.getAssigneeName());
                }
                dto.setDueDate(temp.getDueDate());
                if(temp.getStatus()!=null){
                    dto.setStatus(temp.getStatus());
                }else {
                    if(temp.getFinishTime()!=null){
                        dto.setStatus(1);
                    }else {
                        dto.setStatus(0);
                    }
                }
            }
        }
       // tasks.sort(Comparator.comparing(TaskDto::getCreateTime));
        return JsonResult.success(tasks);
    }

    @Override
    public JsonResult getProcessTaskINfo(String taskId) {
        Task task =  taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task!=null){

        }else {
           HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        }
        return null;
    }

    @Override
    public List<BpmTaskTodoItemRespVO> exportList(BpmQueryVo pageVO) {
        String userId = SecurityUtils.getUsername();
        List<BpmTaskTodoItemRespVO> list = new ArrayList<>();
        if(userId==null){
            userId= "test001";
        }
        // 查询待办任务
        if(pageVO.getStatus()==0){
            // 指定申请人不是当前登录人员则不查询流程实例
            // 申请人与登陆人不匹配，则没有查看流程实例权限
            List<ProcessInstance> processInstancs = new ArrayList<>();
            if(StringUtils.isNotEmpty(pageVO.getProcessId())){
                ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery().active();
                Set<String> pIds = Arrays.stream(pageVO.getProcessId().split(",")).collect(Collectors.toSet());
                processInstanceQuery.processInstanceIds(pIds);
                processInstancs =  processInstanceQuery.list();
            }
            else if(StringUtils.isNotEmpty(pageVO.getId()) && StringUtils.isEmpty(pageVO.getProcessId())){
                processInstancs = new ArrayList<>();
            }
            else if(StringUtils.isNotEmpty(pageVO.getCreateBy()) && !userId.equals(pageVO.getCreateBy())){
                processInstancs = new ArrayList<>();
            }
            else{
                ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery().active().variableValueEquals("startUserId",userId);
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    processInstanceQuery.variableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                    // processInstanceQuery.processInstanceNameLike("%"+pageVO.getProcessName()+"%");
                }
                processInstancs =  processInstanceQuery.list();
            }
            for(ProcessInstance hisInstance:processInstancs){
                //hisInstance.getActivityId()
                if(hisInstance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                BpmTaskTodoItemRespVO dto = new BpmTaskTodoItemRespVO();

                Task task =  taskService.createTaskQuery().processInstanceId(hisInstance.getId()).singleResult();
               /* List<IdentityLink>  calusers = (List<IdentityLink>) task.getIdentityLinks();
                for(IdentityLink identityLink:calusers){
                    //identityLink.getUserId()
                }*/
                if(task!=null){
                    List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(task.getId());
                    String userIds = "";
                    for(HistoricIdentityLink link:links){
                        userIds = userIds+link.getUserId()+",";
                    }
                    userIds = userIds.substring(0,userIds.lastIndexOf(","));
                    SysUser user = remoteUserService.getUserByName(userIds);
                    dto.setName(task.getName());
                    if(user!=null){
                        dto.setStartUserName(user.getNickName());
                    }else {
                        dto.setStartUserName(userIds);
                    }

                }
                Map<String,Object> map = getProcessVariables(hisInstance.getId());
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                if(map.containsKey("serviceType")){
                    dto.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    dto.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    dto.setReason(map.get("reason")+"");
                }
                dto.setServiceId(Long.parseLong(hisInstance.getBusinessKey()));
                dto.setType(hisInstance.getProcessDefinitionKey());
                dto.setStatus(0);
                //dto.setClaimTime(hisInstance.getStartTime());
                dto.setProcessId(hisInstance.getId());
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    dto.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                dto.setCreateTime(hisInstance.getStartTime());
                list.add(dto);
            }
            TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId) // 分配给自己
                    .orderByTaskCreateTime().desc(); // 创建时间倒序
            List<Task> tasks = null;
            if(StringUtils.isNotEmpty(pageVO.getId())){
                String[] arr= pageVO.getId().split(",");
                for(String tId:arr){
                    taskQuery.or().taskId(tId);
                }
                tasks = taskQuery.list();
            }else if(StringUtils.isEmpty(pageVO.getId()) && StringUtils.isNotEmpty(pageVO.getProcessId())){
                tasks = new ArrayList<>();
            }else {
                if (StrUtil.isNotBlank(pageVO.getName())) {
                    taskQuery.taskNameLike("%" + pageVO.getName() + "%");
                }
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    taskQuery.processVariableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                }
                if (pageVO.getStartTime()!=null) {
                    taskQuery.taskCreatedAfter(pageVO.getStartTime());
                }
                if(StrUtil.isNotBlank(pageVO.getCreateBy())){
                    taskQuery.processVariableValueLike("startUserName","%"+pageVO.getCreateBy()+"%");
                }
                //taskQuery.p
                if (pageVO.getEndTime()!=null) {
                    taskQuery.taskCreatedBefore(pageVO.getEndTime());
                }
                tasks = taskQuery.list();
            }

            for(Task task: tasks){
                BpmTaskTodoItemRespVO item = new BpmTaskTodoItemRespVO();
                item.setId(task.getId());
                item.setName(task.getName());
                item.setClaimTime(task.getCreateTime());
                //item.setClaimTime(task.getClaimTime());
                HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                if(instance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                //List<His> historyService.createHistoricVariableInstanceQuery().processInstanceId(task.getProcessInstanceId()).list();
                item.setCreateTime(instance.getStartTime());
                item.setProcessId(task.getProcessInstanceId());
                item.setProcessName(instance.getName());
                item.setStartUserId(instance.getStartUserId());
                item.setProcessDefinitionId(instance.getProcessDefinitionId());
                item.setServiceId(Long.parseLong(instance.getBusinessKey()));
                Map<String,Object> map = getProcessVariables(task.getProcessInstanceId());
                if(map.containsKey("serviceType")){
                    item.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    item.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    item.setReason(map.get("reason")+"");
                }
                if(map.containsKey("startUserId")){
                    item.setStartUserId(map.get("startUserId")+"");
                }
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    item.setStartUserName(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                if(map.containsKey("startUserName")){
                    item.setCreateBy(map.get("startUserName")+"");
                }
                item.setType(instance.getProcessDefinitionKey());
                item.setStatus(0);
                /*//instance.getBusinessKey()
                instance.getProcessVariables()*/
                list.add(item);
            }
            list.sort(Comparator.comparing(BpmTaskTodoItemRespVO::getCreateTime).reversed());
        }else if(pageVO.getStatus()>=1){
            Set<String> finishSet = new HashSet<>();
            List<HistoricProcessInstance> processInstancs = null;
            if(StringUtils.isNotEmpty(pageVO.getProcessId())){
                HistoricProcessInstanceQuery processInstanceQuery =  historyService.createHistoricProcessInstanceQuery().variableValueEquals("startUserId",userId).finished();
                Set<String> pIds = Arrays.stream(pageVO.getProcessId().split(",")).collect(Collectors.toSet());
                processInstanceQuery.processInstanceIds(pIds);
                processInstancs =  processInstanceQuery.list();
            }
            else if(StringUtils.isNotEmpty(pageVO.getId()) && StringUtils.isEmpty(pageVO.getProcessId())){
                processInstancs = new ArrayList<>();
            }
            else if(StringUtils.isNotEmpty(pageVO.getCreateBy()) && !userId.equals(pageVO.getCreateBy())){
                processInstancs = new ArrayList<>();
            }
            else{
                HistoricProcessInstanceQuery processInstanceQuery =  historyService.createHistoricProcessInstanceQuery().variableValueEquals("startUserId",userId).finished();
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    processInstanceQuery.variableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                    //processInstanceQuery.processInstanceNameLike("%"+pageVO.getProcessName()+"%");
                }
                processInstancs =  processInstanceQuery.list();
            }
            for(HistoricProcessInstance hisInstance:processInstancs){
                if(hisInstance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                Map<String,Object> map3 = hisInstance.getProcessVariables();
                BpmTaskTodoItemRespVO dto = new BpmTaskTodoItemRespVO();
                dto.setServiceId(Long.parseLong(hisInstance.getBusinessKey()));
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                dto.setType(hisInstance.getProcessDefinitionKey());
                dto.setCreateTime(hisInstance.getStartTime());
                List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(hisInstance.getId()).variableName("resolveProcessStatus").list();
                Object resolveProcessStatus = null;
                if(variableInstances.size()>0){
                    resolveProcessStatus = variableInstances.get(0).getValue();
                }
                Map<String,Object> map = getProcessVariables(hisInstance.getId());
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                if(map.containsKey("moduleName")){
                    dto.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("serviceType")){
                    dto.setServiceType(map.get("serviceType")+"");
                }
                if(map.containsKey("reason")){
                    dto.setReason(map.get("reason")+"");
                }
                if(map.containsKey("compleateVal")){
                    SysUser user = remoteUserService.getUserByName(map.get("compleateVal")+"");
                    if(user!=null){
                        dto.setStartUserName(user.getNickName());
                    }
                }
                // Object resolveProcessStatus = runtimeService.getVariable(hisInstance.getId(),"resolveProcessStatus");

                //hisInstance.getEndActivityId();
                dto.setClaimTime(hisInstance.getEndTime());
                dto.setProcessId(hisInstance.getId());
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    dto.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                if(resolveProcessStatus==null && pageVO.getStatus()==1){
                    list.add(dto);
                    dto.setStatus(1);
                    finishSet.add(hisInstance.getId());
                }else if(resolveProcessStatus!=null && Integer.parseInt(resolveProcessStatus+"")==2 && pageVO.getStatus()==2){
                    dto.setStatus(2);
                    list.add(dto);
                }
            }

            // 查询已办任务
            HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
                    .taskAssignee(String.valueOf(userId)) // 分配给自己
                    .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
            List<HistoricTaskInstance> tasks = null;
            if(StringUtils.isNotEmpty(pageVO.getId())){
                String[] arr= pageVO.getId().split(",");
                for(String tId:arr){
                    taskQuery.or().taskId(tId);
                }
                tasks = taskQuery.list();
            }else if(StringUtils.isEmpty(pageVO.getId()) && StringUtils.isNotEmpty(pageVO.getProcessId())){
                tasks = new ArrayList<>();
            }else {
                if (StrUtil.isNotBlank(pageVO.getName())) {
                    taskQuery.taskNameLike("%" + pageVO.getName() + "%");
                }
                //taskQuery.
                if (pageVO.getStartTime()!=null) {
                    taskQuery.taskCreatedAfter(pageVO.getStartTime());
                }
                if (pageVO.getEndTime()!=null) {
                    taskQuery.taskCreatedBefore(pageVO.getEndTime());
                }
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    taskQuery.processVariableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                }
                if(StrUtil.isNotBlank(pageVO.getCreateBy())){
                    taskQuery.processVariableValueLike("startUserName","%"+pageVO.getCreateBy()+"%");
                }
                if(pageVO.getStatus()==1){
                    taskQuery.taskVariableValueEquals("resolveTaskStatus",1);
                }
                if(pageVO.getStatus()==2){
                    taskQuery.taskVariableValueEquals("resolveTaskStatus",2);
                }
                // 执行查询
                tasks = taskQuery.list();
            }

            for(HistoricTaskInstance task:tasks){
                BpmTaskTodoItemRespVO item = new BpmTaskTodoItemRespVO();
                item.setId(task.getId());
                item.setName(task.getName());
                //task.get
                item.setCreateTime(task.getCreateTime());
                item.setClaimTime(task.getEndTime());
                HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                if(instance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                if(finishSet.contains(task.getProcessInstanceId())){
                    continue;
                }
                item.setProcessId(task.getProcessInstanceId());
                item.setProcessName(instance.getName());
                item.setStartUserId(instance.getStartUserId());
                item.setProcessDefinitionId(instance.getProcessDefinitionId());
                item.setServiceId(Long.parseLong(instance.getBusinessKey()));
                Map<String,Object> map = getProcessVariables(task.getProcessInstanceId());
                if(map.containsKey("serviceType")){
                    item.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    item.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    item.setReason(map.get("reason")+"");
                }
                if(task.getAssignee()!=null){
                    item.setStartUserId(task.getAssignee());
                    SysUser sysUser = remoteUserService.getUserByName(task.getAssignee());
                    if(sysUser!=null){
                        item.setStartUserName(sysUser.getNickName());
                    }
                }
                if(map.containsKey("startUserName")){
                    SysUser sysUser = remoteUserService.getUserByName(map.get("startUserName")+"");
                    if(sysUser!=null){
                        item.setCreateBy(sysUser.getNickName());
                    }
                }
                item.setType(instance.getProcessDefinitionKey());
                item.setStatus(pageVO.getStatus());

                list.add(item);
            }
            list.sort(Comparator.comparing(BpmTaskTodoItemRespVO::getCreateTime).reversed());
        }
        return list;
    }


    public List<NodeVO> getAllTasks(){
        String[] bpmkey ={"FOB001v1","Fob002V1","Fob003v1","FOB004v1","FOB005v1","FOB006v1","FOB007v1","FOB008v1"};
        List<TaskDto> tasks = new ArrayList<>();
        for(String key:bpmkey){
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(key)
                    .latestVersion()
                    .singleResult();
            if(processDefinition==null){
                continue;
            }
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            if(bpmnModel!=null){
                List<TaskDto> tempTask = BpmTaskUtil.getAllUserTaskEvent(bpmnModel);
                tasks.addAll(tempTask);
            }
        }
        List<NodeVO> nodeVOS = new ArrayList<>();
        for(TaskDto dto:tasks){
            NodeVO vo = new NodeVO();
            vo.setId(dto.getKey());
            vo.setName(dto.getTaskName());
            vo.setTemplateUsage(dto.getTaskName());
            nodeVOS.add(vo);
        }
        return nodeVOS;
    }

    @Override
    public JsonResult getTaskFormData(String serviceType, Long serviceId) {
        String processInstaneId = fobService.getExecuteInstance(serviceType,serviceId);
        Map<String,Object> map = new HashMap<>();
        if(formTemplate!=null && formTemplate.containsKey(serviceType)){
           // String temp = formTemplate.get(serviceType).toString();
            JSONArray jsonNode = (JSONArray) formTemplate.get(serviceType);
            List<FormTemplate> templates = validateTempalee(jsonNode,"-1",processInstaneId);
            // 封装模板信息
           // templates = spDispatchSchemeExecuteService.bingdFormTemplate(templates,serviceType,processInstaneId);
            map.put("templates",templates);
        }
        JsonResult jsonResult = fobService.getServiceFormData(serviceType,processInstaneId,serviceId);
        map.put("data",jsonResult.getResultObject());
        return JsonResult.success(map);
    }

    @Override
    public List<BpmTaskTodoItemRespVO> taskExportList(BpmQueryVo taskReqVo) {
        return null;
    }

    @Override
    public JsonResult  getProcessAllTasks(String processInstaneId) {
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstaneId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
        if(processDefinition == null){
            return JsonResult.failed("流程定义不存在，请联系管理员确认后重新发起");
        }
        List<TaskDto> tasks = null;
        if(taskMap.containsKey(instance.getProcessDefinitionId())){
            tasks = taskMap.get(instance.getProcessDefinitionId());
        }else {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
            tasks = readBpmNodeInfo(processDefinition.getKey(),instance.getProcessDefinitionId(),bpmnModel);
        }
        SpDispatchSchemeExecute execute = spDispatchSchemeExecuteService.getExceuteByInstanceId(processInstaneId);
        String assigners = null;
        if(execute!=null){
            assigners = execute.getAssigeners();
        }else {
            SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(processInstaneId);
            if(spFobSublease!=null){
                assigners = spFobSublease.getAssigeners();
            }
        }
        List<BpmTaskDto> list = findActivitiOrFinishTask(processInstaneId);
        Map<String,BpmTaskDto> maps = list.stream().collect(Collectors.toMap(BpmTaskDto::getCategory,item->item));
        for(TaskDto dto : tasks){
            dto.setStatus(-1);
            dto.setParentNode(null);
            if(maps.containsKey(dto.getKey())){
                BpmTaskDto temp = maps.get(dto.getKey());
                dto.setTaskId(temp.getTaskId());
                dto.setComment(temp.getComment());
                dto.setCreateTime(temp.getCreateTime());
                dto.setFinishTime(temp.getFinishTime());
                dto.setDuration(temp.getDuration());
                dto.setAssigneeId(temp.getAssigneeId());
                dto.setAssigneeName(temp.getAssigneeName());
                dto.setDueDate(temp.getDueDate());
                if(temp.getFinishTime()!=null){
                    dto.setStatus(1);
                }else {
                    dto.setStatus(0);
                }
            }
           SpFobBaseBean spFobBaseBean = spDispatchSchemeExecuteService.getAssigenersByNode(processInstaneId,dto.getKey());
           if(spFobBaseBean!=null && spFobBaseBean.getStatus()!=null){
               dto.setStatus(spFobBaseBean.getStatus());
           }
           if(spFobBaseBean!=null && dto.getDueDate()==null && spFobBaseBean.getPlanEndDate()!=null){
               dto.setDueDate(spFobBaseBean.getPlanEndDate());
           }
            if(spFobBaseBean!=null && !"".equals(spFobBaseBean.getAddAssigeners())){
               dto.setAddAssigeners(spFobBaseBean.getAddAssigeners());
           }else{
                if(assigners!=null){
                    dto.setAddAssigeners(assigners);
                }
           }
           if(formTemplate!=null && formTemplate.containsKey(dto.getKey())){
                String temp = formTemplate.get(dto.getKey()).toString();
                JSONArray jsonNode = (JSONArray) formTemplate.get(dto.getKey());
                List<FormTemplate> templates = validateTempalee(jsonNode,instance.getBusinessKey(),processInstaneId);
                // 封装模板信息
                templates = spDispatchSchemeExecuteService.bingdFormTemplate(templates,dto.getKey(),processInstaneId);
                dto.setFormTemplate(templates);
            }
        }
        tasks.sort(Comparator.comparing(TaskDto::getKey));
        List<TaskDto> list1 = tasks.stream().filter(item->item.getStatus()==0).collect(Collectors.toList());
        List<TaskDto> list2 = tasks.stream().filter(item->item.getStatus()==-1).collect(Collectors.toList());
        List<TaskDto> list3 = tasks.stream().filter(item->item.getStatus()==1).collect(Collectors.toList());
        list1.addAll(list2);
        list1.addAll(list3);
        Map<String,Object> map = new HashMap<>();
        map.put("data",list1);
        map.put("processKey",processDefinition.getKey());
        return JsonResult.success(map);
    }

    @Autowired
    ConShippingService conShippingService;

    public List<FormTemplate> validateTempalee(JSONArray array,String bussKey,String processInstanceId){
        List<FormTemplate> templates = new ArrayList<>();
        for (Object item : array){
            JSONObject object = (JSONObject) item;
            FormTemplate template = new FormTemplate();
            template.setId(object.get("id").toString());
            template.setName(object.get("name").toString());
            JSONArray childs = (JSONArray) object.get("template");
            List<Field> fields = new ArrayList<>();
            for(Object child:childs){
                Field tempField = new Field();
                JSONObject childItem = (JSONObject) child;
                if(childItem.containsKey("fieldCode")){
                    tempField.setFieldCode(childItem.get("fieldCode").toString());
                }
                tempField.setUnit(childItem.get("unit")!=null?childItem.get("unit").toString():"");
                tempField.setLimit(childItem.get("limit")!=null?childItem.get("limit").toString():"");
                tempField.setIsRequest(childItem.get("isRequest")!=null?childItem.get("isRequest").toString():"");
                tempField.setIsDisplay(childItem.get("isDisplay")!=null?childItem.get("isDisplay").toString():"");
                tempField.setFieldName(childItem.get("fieldName").toString());
                tempField.setType(childItem.get("type").toString());
                tempField.setDataType(childItem.get("dataType")!=null?childItem.get("dataType").toString():"");
                if("emailTemplate".equals(childItem.get("dataType"))){ // 邮件模板
                    String tempKey = template.getId().substring(0,template.getId().lastIndexOf("-"));
                    List<FieldOptions> options = spFobTemplateService.getTemplateInfoByServiceKey(tempKey,"email");
                    tempField.setOptions(options);
                } else if("fileTemplate".equals(childItem.get("dataType"))){ // 邮件模板
                    String tempKey = template.getId().substring(0,template.getId().lastIndexOf("-"));
                    List<FieldOptions> options = spFobTemplateService.getTemplateInfoByServiceKey(tempKey,"file");
                    tempField.setOptions(options);
                }
                else if("cron".equals(tempField.getDataType())){ // 合同
                    List<FieldOptions> options = spFobTemplateService.getCronInfo(childItem.get("datakey").toString(),bussKey);
                    tempField.setOptions(options);
                }else if("SpPortInformation".equals(tempField.getDataType())){
                    List<SpPortInformation> spPortInformations =  spPortInformationMapper.selectList(new LambdaQueryWrapper<SpPortInformation>());
                    List<FieldOptions> options = new ArrayList<>();
                    for(SpPortInformation information:spPortInformations){
                        FieldOptions options1 = new FieldOptions();
                        options1.setId(information.getPortNameEnglish());
                        options1.setName(information.getPortNameEnglish());
                        options.add(options1);
                    }
                    tempField.setOptions(options);
                } else if("notice".equals(tempField.getDataType())){ // 通知
                    SpFobSublease spFobSublease = spFobSubleaseService.getExceuteByInstanceId(processInstanceId);
                    List<FieldOptions> options = new ArrayList<>();
                    if(spFobSublease!=null){
                        ConShipping conShipping =  conShippingService.getById(spFobSublease.getConId());
                        if(conShipping!=null && StringUtils.isNotEmpty(conShipping.getRedeliveryNotice())){
                            try{
                                List<Map> nodes = JsonUtils.jsonToList(conShipping.getRedeliveryNotice(), Map.class);
                                List<Integer> deliveryNoticeDays = new ArrayList<>();
                                nodes.forEach(node->{
                                    deliveryNoticeDays.add(Integer.parseInt(node.get("deliveryNoticeDay")+""));
                                });
                                       // = nodes.stream().map(node->node.get("deliveryNoticeDay").asInt()).collect(Collectors.toList());
                                Collections.sort(deliveryNoticeDays);
                                for(Integer num:deliveryNoticeDays){
                                    FieldOptions options1 = new FieldOptions();
                                    options1.setId(num+"");
                                    options1.setName(num+"");
                                    options.add(options1);
                                }
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }
                    tempField.setOptions(options);
                    //List<FieldOptions> options = spFobTemplateService.getCronInfo(childItem.get("datakey").toString(),bussKey);
                }else if(childItem.get("options")!=null){
                    JSONArray op = (JSONArray) childItem.get("options");
                    String json = JsonUtils.objectToJson(op);
                    try {
                        List<FieldOptions> options = JsonUtils.jsonToList(json,FieldOptions.class);
                        tempField.setOptions(options);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(childItem.get("nodes")!=null){
                    JSONArray op = (JSONArray) childItem.get("nodes");
                    String json = JsonUtils.objectToJson(op);
                    try {
                        List<Field> list = JsonUtils.jsonToList(json,Field.class);
                        tempField.setNodes(list);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
                fields.add(tempField);
            }
            template.setTemplate(fields);
            templates.add(template);
        }
        return templates;
    }

    /**
     * 流程完成时间处理
     *
     * @param ms
     * @return
     */
    private String getDate(long ms) {

        long day = ms / (24 * 60 * 60 * 1000);
        long hour = (ms / (60 * 60 * 1000) - day * 24);
        long minute = ((ms / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long second = (ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);

        if (day > 0) {
            return day + "天" + hour + "小时" + minute + "分钟";
        }
        if (hour > 0) {
            return hour + "小时" + minute + "分钟";
        }
        if (minute > 0) {
            return minute + "分钟";
        }
        if (second > 0) {
            return second + "秒";
        } else {
            return 0 + "秒";
        }
    }

    public List<TaskDto>  readBpmNodeInfo(String key,String id,BpmnModel bpmnModel){
        Map<String,List<TaskDto>> maps = new HashMap<>();
        List<TaskDto> tasks = BpmTaskUtil.getAllUserTaskEvent(bpmnModel);
        maps.put(id,tasks);
        if(taskMap ==null){
            taskMap = new HashMap<>();
        }
        // 封装节点坐标
        List<SpBpmCoordinate> list = spBpmCoordinateService.list(new LambdaQueryWrapper<SpBpmCoordinate>()
                .eq(SpBpmCoordinate::getBpmKey,key)
        );
        Map<String,SpBpmCoordinate> map = list.stream().collect(Collectors.toMap(SpBpmCoordinate::getNode, (p) -> p));
        for(TaskDto dto:tasks){
            if(map.containsKey(dto.getKey())){
                SpBpmCoordinate temp = map.get(dto.getKey());
                if(temp!=null){
                    dto.setX(temp.getX());
                    dto.setY(temp.getY());
                }
            }
        }
        taskMap.put(id,tasks);
        return tasks;
    }

    public Map readJsonFile() {
        try{
            ClassPathResource resource = new ClassPathResource("form_template.json");
            InputStream inputStream = resource.getInputStream();
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode myObject = objectMapper.readValue(inputStream, JsonNode.class);
            Map mode = JSONUtil.toBean(myObject.toString(),Map.class);
            return mode;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Override
    public String getNodeNameByKey(String key){
        if(this.formTemplate.containsKey(key)){
            JSONArray jsonNode = (JSONArray) formTemplate.get(key);
            JSONObject object = (JSONObject) jsonNode.get(0);
            //List<Map<String,String>> fields =  JsonUtils.jsonToList( this.formTemplate.get(key).toString(), Map.class);
            return object.get("name").toString();
        }
        return "";
    }

    @Override
    public void addVaribals(Map<String, Object> map,String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task!=null){
           taskService.setVariables(task.getId(),map);
        }
    }

    @Override
    public String getTaskName(String taskId) {
        HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        //Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(task!=null){
            return task.getName();
        }
        return "";
    }

    @Override
    public List<TaskDto> findTaskIdNextNode(String processInstaneId, String taskSId) {
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstaneId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
        List<TaskDto> tasks = null;
        if(taskMap.containsKey(instance.getProcessDefinitionId())){
            tasks = taskMap.get(instance.getProcessDefinitionId());
        }else {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
            tasks = readBpmNodeInfo(processDefinition.getKey(),instance.getProcessDefinitionId(),bpmnModel);
        }
        List<BpmTaskDto> list = findActivitiOrFinishTaskResult(processInstaneId);
        Map<String,BpmTaskDto> maps = list.stream().collect(Collectors.toMap(BpmTaskDto::getCategory,item->item));
        TaskDto rebackNode = null;
        for(TaskDto dto : tasks){
            dto.setStatus(-1);
            dto.setParentNode(null);
            if(maps.containsKey(dto.getKey())){
                BpmTaskDto temp = maps.get(dto.getKey());
                dto.setTaskId(temp.getTaskId());
            }
            SpFobBaseBean spFobBaseBean = spDispatchSchemeExecuteService.getAssigenersByNode(processInstaneId,dto.getKey());
            if(spFobBaseBean!=null && spFobBaseBean.getStatus()!=null){
                dto.setStatus(spFobBaseBean.getStatus());
            }
            if(taskSId.equals(dto.getTaskId())){
                rebackNode = dto;
            }
        }
        // 获取待撤回任务信息
        List<TaskDto> result = new ArrayList<>();
        if(rebackNode!=null && rebackNode.getNextNode()!=null && rebackNode.getNextNode().length()>0){
            waitRebackTask(result,tasks,rebackNode.getNextNode());
        }
        return result;
    }

    @Override
    public List<TaskDto> findTaskIdStartNode(String processInstaneId, String taskSId) {
        HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstaneId).singleResult();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(instance.getProcessDefinitionId()).singleResult();
        List<TaskDto> tasks = null;
        if(taskMap.containsKey(instance.getProcessDefinitionId())){
            tasks = taskMap.get(instance.getProcessDefinitionId());
        }else {
            BpmnModel bpmnModel = repositoryService.getBpmnModel(instance.getProcessDefinitionId());
            tasks = readBpmNodeInfo(processDefinition.getKey(),instance.getProcessDefinitionId(),bpmnModel);
        }
        List<BpmTaskDto> list = findActivitiOrFinishTaskResult(processInstaneId);
        Map<String,BpmTaskDto> maps = list.stream().collect(Collectors.toMap(BpmTaskDto::getCategory,item->item));
        TaskDto rebackNode = null;
        for(TaskDto dto : tasks){
            dto.setStatus(-1);
            dto.setParentNode(null);
            if(maps.containsKey(dto.getKey())){
                BpmTaskDto temp = maps.get(dto.getKey());
                dto.setTaskId(temp.getTaskId());
            }
            SpFobBaseBean spFobBaseBean = spDispatchSchemeExecuteService.getAssigenersByNode(processInstaneId,dto.getKey());
            if(spFobBaseBean!=null && spFobBaseBean.getStatus()!=null){
                dto.setStatus(spFobBaseBean.getStatus());
            }
            if(taskSId.equals(dto.getTaskId())){
                rebackNode = dto;
            }
        }
        // 获取待撤回任务信息
        List<TaskDto> result = new ArrayList<>();
        if(rebackNode!=null && rebackNode.getNextNode()!=null && rebackNode.getNextNode().length()>0){
            waitStartTask(result,tasks,rebackNode.getNextNode());
        }
        return result;
    }

    @Override
    public JsonResult<Page<BpmTaskTodoItemRespVO>> todoPageList(BpmQueryVo pageVO) {
        String userId = SecurityUtils.getUsername();
        Page<BpmTaskTodoItemRespVO> page = new Page();
        List<BpmTaskTodoItemRespVO> list = new ArrayList<>();
        if(userId==null){
            userId= "test001";
        }
        // 查询待办任务
        if(pageVO.getStatus()==0){
            // 指定申请人不是当前登录人员则不查询流程实例
            // 申请人与登陆人不匹配，则没有查看流程实例权限
            List<ProcessInstance> processInstancs = new ArrayList<>();
            if(StringUtils.isNotEmpty(pageVO.getCreateBy()) && !userId.equals(pageVO.getCreateBy())){
                processInstancs = new ArrayList<>();
            }else{
                ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery().active().variableValueEquals("startUserId",userId);
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    processInstanceQuery.variableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                    // processInstanceQuery.processInstanceNameLike("%"+pageVO.getProcessName()+"%");
                }
                processInstancs =  processInstanceQuery.list();
            }
            for(ProcessInstance hisInstance:processInstancs){
                //hisInstance.getActivityId()
                if(hisInstance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                BpmTaskTodoItemRespVO dto = new BpmTaskTodoItemRespVO();

                Task task =  taskService.createTaskQuery().processInstanceId(hisInstance.getId()).singleResult();
               /* List<IdentityLink>  calusers = (List<IdentityLink>) task.getIdentityLinks();
                for(IdentityLink identityLink:calusers){
                    //identityLink.getUserId()
                }*/
               if(task!=null){
                   List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(task.getId());
                   String userIds = "";
                   for(HistoricIdentityLink link:links){
                       userIds = userIds+link.getUserId()+",";
                   }
                   userIds = userIds.substring(0,userIds.lastIndexOf(","));
                   SysUser user = remoteUserService.getUserByName(userIds);
                   dto.setName(task.getName());
                   if(user!=null){
                       dto.setStartUserName(user.getNickName());
                   }else {
                       dto.setStartUserName(userIds);
                   }

               }
                Map<String,Object> map = getProcessVariables(hisInstance.getId());
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                if(map.containsKey("serviceType")){
                    dto.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    dto.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    dto.setReason(map.get("reason")+"");
                }
                dto.setServiceId(Long.parseLong(hisInstance.getBusinessKey()));
                dto.setType(hisInstance.getProcessDefinitionKey());
                dto.setStatus(0);
                //dto.setClaimTime(hisInstance.getStartTime());
                dto.setProcessId(hisInstance.getId());
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    dto.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                dto.setCreateTime(hisInstance.getStartTime());
                list.add(dto);
            }
            TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId) // 分配给自己
                    .orderByTaskCreateTime().desc(); // 创建时间倒序
            if (StrUtil.isNotBlank(pageVO.getName())) {
                taskQuery.taskNameLike("%" + pageVO.getName() + "%");
            }
            if(StrUtil.isNotBlank(pageVO.getProcessName())){
                taskQuery.processVariableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
            }
            if (pageVO.getStartTime()!=null) {
                taskQuery.taskCreatedAfter(pageVO.getStartTime());
            }
            if(StrUtil.isNotBlank(pageVO.getCreateBy())){
                taskQuery.processVariableValueLike("startUserName","%"+pageVO.getCreateBy()+"%");
            }
            //taskQuery.p
            if (pageVO.getEndTime()!=null) {
                taskQuery.taskCreatedBefore(pageVO.getEndTime());
            }
            List<Task> tasks = taskQuery.list();
            for(Task task: tasks){
                BpmTaskTodoItemRespVO item = new BpmTaskTodoItemRespVO();
                item.setId(task.getId());
                item.setName(task.getName());
                item.setClaimTime(task.getCreateTime());
                //item.setClaimTime(task.getClaimTime());
                HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                if(instance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                //List<His> historyService.createHistoricVariableInstanceQuery().processInstanceId(task.getProcessInstanceId()).list();
                item.setCreateTime(instance.getStartTime());
                item.setProcessId(task.getProcessInstanceId());
                item.setProcessName(instance.getName());
                item.setStartUserId(instance.getStartUserId());
                item.setProcessDefinitionId(instance.getProcessDefinitionId());
                item.setServiceId(Long.parseLong(instance.getBusinessKey()));
                Map<String,Object> map = getProcessVariables(task.getProcessInstanceId());
                if(map.containsKey("serviceType")){
                    item.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    item.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    item.setReason(map.get("reason")+"");
                }
                if(map.containsKey("startUserId")){
                    item.setStartUserId(map.get("startUserId")+"");
                }
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    item.setStartUserName(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                if(map.containsKey("startUserName")){
                    item.setCreateBy(map.get("startUserName")+"");
                }
                item.setType(instance.getProcessDefinitionKey());
                item.setStatus(0);
                /*//instance.getBusinessKey()
                instance.getProcessVariables()*/
                list.add(item);
            }
            list.sort(Comparator.comparing(BpmTaskTodoItemRespVO::getCreateTime).reversed());
            List<BpmTaskTodoItemRespVO> result = getPage(list,pageVO.getPageNum(),pageVO.getPageSize());
            page.setList(result);
            page.setTotal(list.size());
        }else if(pageVO.getStatus()>=1){
            Set<String> finishSet = new HashSet<>();
            List<HistoricProcessInstance> processInstancs = null;
            if(StringUtils.isNotEmpty(pageVO.getCreateBy()) && !StringUtils.equals(userId,pageVO.getCreateBy())){
                processInstancs = new ArrayList<>();
            }else{
                HistoricProcessInstanceQuery processInstanceQuery =  historyService.createHistoricProcessInstanceQuery().variableValueEquals("startUserId",userId).finished();
                if(StrUtil.isNotBlank(pageVO.getProcessName())){
                    processInstanceQuery.variableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
                    //processInstanceQuery.processInstanceNameLike("%"+pageVO.getProcessName()+"%");
                }
                processInstancs =  processInstanceQuery.list();
            }
            for(HistoricProcessInstance hisInstance:processInstancs){
                if(hisInstance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                Map<String,Object> map3 = hisInstance.getProcessVariables();
                BpmTaskTodoItemRespVO dto = new BpmTaskTodoItemRespVO();
                dto.setServiceId(Long.parseLong(hisInstance.getBusinessKey()));
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                dto.setType(hisInstance.getProcessDefinitionKey());
                dto.setCreateTime(hisInstance.getStartTime());
                List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(hisInstance.getId()).variableName("resolveProcessStatus").list();
                Object resolveProcessStatus = null;
                if(variableInstances.size()>0){
                    resolveProcessStatus = variableInstances.get(0).getValue();
                }
                Map<String,Object> map = getProcessVariables(hisInstance.getId());
                dto.setProcessName(hisInstance.getProcessDefinitionName());
                if(map.containsKey("moduleName")){
                    dto.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("serviceType")){
                    dto.setServiceType(map.get("serviceType")+"");
                }
                if(map.containsKey("reason")){
                    dto.setReason(map.get("reason")+"");
                }
                if(map.containsKey("compleateVal")){
                    SysUser user = remoteUserService.getUserByName(map.get("compleateVal")+"");
                    if(user!=null){
                        dto.setStartUserName(user.getNickName());
                    }
                }
               // Object resolveProcessStatus = runtimeService.getVariable(hisInstance.getId(),"resolveProcessStatus");

               //hisInstance.getEndActivityId();
                dto.setClaimTime(hisInstance.getEndTime());
                dto.setProcessId(hisInstance.getId());
                if(SecurityUtils.getLoginUser()!=null && SecurityUtils.getLoginUser().getSysUser()!=null){
                    dto.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName());
                }
                if(resolveProcessStatus==null && pageVO.getStatus()==1){
                    list.add(dto);
                    dto.setStatus(1);
                    finishSet.add(hisInstance.getId());
                }else if(resolveProcessStatus!=null && Integer.parseInt(resolveProcessStatus+"")==2 && pageVO.getStatus()==2){
                    dto.setStatus(2);
                    list.add(dto);
                }
            }
            // 查询已办任务
            HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().finished() // 已完成
                    .taskAssignee(String.valueOf(userId)) // 分配给自己
                    .orderByHistoricTaskInstanceEndTime().desc(); // 审批时间倒序
            if (StrUtil.isNotBlank(pageVO.getName())) {
                taskQuery.taskNameLike("%" + pageVO.getName() + "%");
            }
            //taskQuery.
            if (pageVO.getStartTime()!=null) {
                taskQuery.taskCreatedAfter(pageVO.getStartTime());
            }
            if (pageVO.getEndTime()!=null) {
                taskQuery.taskCreatedBefore(pageVO.getEndTime());
            }
            if(StrUtil.isNotBlank(pageVO.getProcessName())){
                taskQuery.processVariableValueLike("moduleName","%"+pageVO.getProcessName()+"%");
            }
            if(StrUtil.isNotBlank(pageVO.getCreateBy())){
                taskQuery.processVariableValueLike("startUserName","%"+pageVO.getCreateBy()+"%");
            }
            if(pageVO.getStatus()==1){
                taskQuery.taskVariableValueEquals("resolveTaskStatus",1);
            }
            if(pageVO.getStatus()==2){
                taskQuery.taskVariableValueEquals("resolveTaskStatus",2);
            }
            // 执行查询
            List<HistoricTaskInstance> tasks = taskQuery.list();
            for(HistoricTaskInstance task:tasks){
                BpmTaskTodoItemRespVO item = new BpmTaskTodoItemRespVO();
                item.setId(task.getId());
                item.setName(task.getName());
                //task.get
                item.setCreateTime(task.getCreateTime());
                item.setClaimTime(task.getEndTime());
                HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                if(instance.getProcessDefinitionId().contains("FOB")){
                    continue;
                }
                if(finishSet.contains(task.getProcessInstanceId())){
                    continue;
                }
                item.setProcessId(task.getProcessInstanceId());
                item.setProcessName(instance.getName());
                item.setStartUserId(instance.getStartUserId());
                item.setProcessDefinitionId(instance.getProcessDefinitionId());
                item.setServiceId(Long.parseLong(instance.getBusinessKey()));
                Map<String,Object> map = getProcessVariables(task.getProcessInstanceId());
                if(map.containsKey("serviceType")){
                    item.setServiceType(map.get("serviceType").toString());
                }
                if(map.containsKey("moduleName")){
                    item.setProcessName(map.get("moduleName")+"");
                }
                if(map.containsKey("reason")){
                    item.setReason(map.get("reason")+"");
                }
                if(task.getAssignee()!=null){
                    item.setStartUserId(task.getAssignee());
                    SysUser sysUser = remoteUserService.getUserByName(task.getAssignee());
                    if(sysUser!=null){
                        item.setStartUserName(sysUser.getNickName());
                    }
                }
                if(map.containsKey("startUserName")){
                    SysUser sysUser = remoteUserService.getUserByName(map.get("startUserName")+"");
                    if(sysUser!=null){
                        item.setCreateBy(sysUser.getNickName());
                    }
                }
                item.setType(instance.getProcessDefinitionKey());
                item.setStatus(pageVO.getStatus());

                list.add(item);
            }
            list.sort(Comparator.comparing(BpmTaskTodoItemRespVO::getCreateTime).reversed());
            List<BpmTaskTodoItemRespVO> result = getPage(list,pageVO.getPageNum(),pageVO.getPageSize());
            page.setList(result);
            page.setTotal(list.size());
        }
        return JsonResult.success(page);
    }


    /**
     * 手动分页
     *
     * @param originList 分页前数据
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 分页后结果
     */
    public <T> List<T> getPage(List<T> originList, Integer pageNum, Integer pageSize) {
        // 如果页码为空或者每页数量为空
        pageNum = pageNum == null ? 0 : pageNum;
        pageSize = pageSize == null ? 0 : pageSize;

        // 分页后的结果
        List<T> resultList = new ArrayList<>();

        // 如果需要进行分页
        if (pageNum > 0 && pageSize > 0) {
            // 获取起点
            int pageStart = (pageNum - 1) * pageSize;
            // 获取终点
            int pageStop = pageStart + pageSize;
            // 开始遍历
            while (pageStart < pageStop) {
                // 考虑到最后一页可能不够pageSize
                if (pageStart >= originList.size()) {
                    break;
                }
                resultList.add(originList.get(pageStart++));
            }
        }

        // 如果不进行分页
        else {
            // 显示所有数据
            resultList = originList;
        }
        return resultList;
    }


    public Map<String,Object> getProcessVariables(String processInstanceId){
        Map<String,Object> map = new HashMap<>();
        List<HistoricVariableInstance> list =  historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
        list.forEach(item->map.put(item.getVariableName(),item.getValue()));
        return map;
    }

    @Resource
    @Lazy
    ConBpmResultService conBpmResultService;

    @Resource
    @Lazy
    FobService fobService;

    @Resource
    @Lazy
    SpDispatchSchemeDetailService spDispatchSchemeDetailService;

    @Resource
    @Lazy
    SpDispatchService spDispatchService;

    @Resource
    @Lazy
    SpArrangeSchemeService spArrangeSchemeService;

    @Resource
    @Lazy
    SpPaymentOrderService spPaymentOrderService;
    @Resource
    @Lazy
    SmShipCrewService smShipCrewService;

    @Resource
    @Lazy
    SmShipReportService smShipReportService;

    @Resource
    @Lazy
    SpOverhaulService spOverhaulService;

    @Transactional
    @Override
    public void approveTask(String userId, BpmTaskApproveReqVO reqVO) {
        Task task = taskService.createTaskQuery().taskId(reqVO.getId()).singleResult();
        if(task==null){
            throw new BusException("任务不存在，请核对后重新操作", BaseResultCode.GENERAL_ERROR);
        }
        taskService.addComment(reqVO.getId(), task.getProcessInstanceId(), BpmComment.NORMAL.getType(), reqVO.getReason());
        taskService.setAssignee(reqVO.getId(), SecurityUtils.getUsername());
        //taskService.setVariableLocal();
        Map<String,Object> map = new HashMap<>();
        if(1==reqVO.getType()){
            map.put("resolveTaskStatus",1);
            taskService.setVariableLocal(reqVO.getId(),"resolveTaskStatus",1);
            taskService.complete(reqVO.getId(), map);
        }else if(2==reqVO.getType()){
            //拒绝任务
            HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            //设置拒绝参数
            runtimeService.setVariable(processInstance.getId(),"resolveProcessStatus",2);
            //historyService.
            //调用任务状态处理逻辑
            if(processInstance.getProcessDefinitionKey().startsWith("con") || processInstance.getProcessDefinitionKey().startsWith("saveClause")){
                conBpmResultService.updateConResult(processInstance.getBusinessKey(),2,processInstance.getProcessDefinitionKey());
            }else if(processInstance.getProcessDefinitionKey().startsWith("spPayOrder")){
                //Map<String,Object> params =  processInstance.getProcessVariables();
                HistoricVariableInstance variable= historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).variableName("serviceType").singleResult();
                String serviceType = "";
                if(variable!=null){
                    serviceType = variable.getValue().toString();
                }
                fobService.updateApprovaResult(processInstance.getBusinessKey(),2,processInstance.getProcessDefinitionKey(),serviceType);
            }else if(processInstance.getProcessDefinitionKey().startsWith("spYearPlan")){
                spDispatchSchemeDetailService.yearPlanSchemeApproveBack(processInstance.getBusinessKey(),2);
            } else if(processInstance.getProcessDefinitionKey().startsWith("spDispatchScheme")){
                spDispatchService.dispatchSchemeApproveBack(processInstance.getBusinessKey(),2);
            } else if(processInstance.getProcessDefinitionKey().startsWith("spDispatchScheme")){
                Map<String,Object> params =  new HashMap<>();
                List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).list();
                for(HistoricVariableInstance variableInstance:variableInstances){
                    params.put(variableInstance.getVariableName(),variableInstance.getValue());
                }
                spArrangeSchemeService.arrangeSchemeApproveBack(params,Long.parseLong(processInstance.getBusinessKey()),2);
            }else if(processInstance.getProcessDefinitionKey().equals(BpmInstanceServiceApi.SYSTEM_DELETE_BPM_KEY)){
                String module = "";
                Integer serviceType = null;
                List<HistoricVariableInstance> variableInstances = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstance.getId()).list();
                for(HistoricVariableInstance variableInstance:variableInstances){
                    if(variableInstance.getVariableName().equals("module")){
                        module = variableInstance.getValue().toString();
                    }
                    if(variableInstance.getVariableName().equals("serviceType")){
                        serviceType = Integer.parseInt(variableInstance.getValue().toString());
                    }
                }
                //runtimeService.createpro
                Map<String,Object> params =  processInstance.getProcessVariables();
                if(module.equals("con")){
                    //Integer serviceType = (Integer) params.get("serviceType");
                    conBpmResultService.deleteConResult(processInstance.getBusinessKey(),2,processInstance.getProcessDefinitionKey(),serviceType);
                }else if(module.equals("payOrder")){
                    if(serviceType==1){
                        SpPaymentOrder spPaymentOrder = spPaymentOrderService.getById(processInstance.getBusinessKey());
                        spPaymentOrder.setApproverStatus(2);
                        spPaymentOrderService.updateById(spPaymentOrder);
                    }
                }else if(module.equals("shipCrew")){
                    if(serviceType==1){
                        smShipCrewService.cancelDelete(processInstance.getBusinessKey(),2);
                    }
                }else if(module.equals("shipReport")){
                    if(serviceType==1){
                        smShipReportService.cancelDelete(processInstance.getBusinessKey(),2);
                    }
                }else if(module.equals("spOverhaul")) {
                   // Integer serviceType = Integer.parseInt(params.get("serviceType") + "");
                    if (serviceType == 1) {
                        spOverhaulService.cancelDelete(processInstance.getBusinessKey(), 2);
                    }
                }else if(module.equals("tzFuelReport")) {
                    if (serviceType == 1) {
                        tzFuelReportService.dataDeleteRollback(processInstance.getBusinessKey(), 2);
                    }
                }else if(module.equals("dispatchGoodsDelete")) {
                    if (serviceType == 1) {
                        spDispatchSchemeDetailService.dataDeleteRollback(processInstance.getBusinessKey(),2);
                    }
                }
            }
            map.put("resolveTaskStatus",2);
            taskService.setVariableLocal(reqVO.getId(),"resolveTaskStatus",2);
            taskService.setVariableLocal(reqVO.getId(),"compleateVal",SecurityUtils.getUsername());
            taskService.complete(reqVO.getId(),map);
            try{
                runtimeService.deleteProcessInstance(processInstance.getId(), "拒绝任务");
            }catch (Exception e){

            }
        }
    }

    @Override
    public JsonResult<List<TaskDto>> getTaskInfo(String definitionId) {
        Model model =  repositoryService.getModel(definitionId);
        ProcessDefinition processDefinition = processDefinitionService.getProcessDefinitionByDeploymentId(model.getDeploymentId());
        //ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(model.getKey()).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        List<TaskDto> tasks = readBpmNodeInfo(processDefinition.getKey(),processDefinition.getId(),bpmnModel);
        return JsonResult.success(tasks);
    }

    public static <T, U> Set<U> convertSet(Collection<T> from, Function<T, U> func) {
        if (CollUtil.isEmpty(from)) {
            return new HashSet<>();
        }
        return from.stream().map(func).filter(Objects::nonNull).collect(Collectors.toSet());
    }
    public int getStart(BpmQueryVo pageParam) {
        return (pageParam.getPageNum() - 1) * pageParam.getPageSize();
    }
    public void waitStartTask(List<TaskDto> result, List<TaskDto> list,String taskSid){
        if(taskSid!=null && taskSid.length()>0){
            String[] sids = taskSid.split(",");
            for (String sid :sids){
                TaskDto tempDto = null;
                boolean flag = true;
                for(TaskDto dto:list){
                    if(sid.equals(dto.getId())){
                        tempDto = dto;
                        if(!flag){
                            break;
                        }
                    }
                    if(dto.getNextNode()!=null && dto.getNextNode().contains(sid)){
                        if(dto.getStatus()!=1){
                            flag = false;
                            if(tempDto!=null){
                                break;
                            }
                        }
                    }
                }
                if(tempDto!=null && tempDto.getStatus()==-1 && flag){
                    result.add(tempDto);
                }
            }
        }
    }

    public void waitRebackTask(List<TaskDto> result, List<TaskDto> list,String taskSid){
        if(taskSid!=null && taskSid.length()>0){
            String[] sids = taskSid.split(",");
            for (String sid :sids){
                TaskDto tempDto = null;
                for(TaskDto dto:list){
                    if(sid.equals(dto.getId())){
                        tempDto = dto;
                    }
                }
                if(tempDto!=null && tempDto.getStatus()!=-1){
                    result.add(tempDto);
                    if(tempDto.getNextNode()!=null && tempDto.getNextNode().length()>0 && tempDto.getStatus()==1){
                        waitRebackTask(result,list,tempDto.getNextNode());
                    }
                }
            }
        }
    }

}
